package com.jwong.grpc.jwtauth;

import io.grpc.CallCredentials;
import io.grpc.Metadata;
import io.grpc.Status;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.concurrent.Executor;

/**
 * CallCredentials 实现，它携带 JWT 值，
 * 该值将在请求元数据中使用“Authorization”键和“Bearer”类型传播到服务器。
 */
public class JwtCredential extends CallCredentials {

  private final String subject;

  JwtCredential(String subject) {
    this.subject = subject;
  }

  @Override
  public void applyRequestMetadata(final RequestInfo requestInfo, final Executor executor,
      final MetadataApplier metadataApplier) {
    // 制作一个 JWT compact序列化字符串
    // 此示例省略了设置过期时间，但实际应用程序应该这样做。
    final String jwt =
        Jwts.builder()
            .setSubject(subject)
            .signWith(SignatureAlgorithm.HS256, Constant.JWT_SIGNING_KEY)
            .compact();

    executor.execute(() -> {
      try {
        Metadata headers = new Metadata();
        headers.put(Constant.AUTHORIZATION_METADATA_KEY,
            String.format("%s %s", Constant.BEARER_TYPE, jwt));
        metadataApplier.apply(headers);
      } catch (Throwable e) {
        metadataApplier.fail(Status.UNAUTHENTICATED.withCause(e));
      }
    });
  }

  @Override
  public void thisUsesUnstableApi() {
  }
}
